package annotation.test2;



import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.*;
//串讲步骤4: 创建ClassUtils工具类,根据报名得到包下的所有类对象, 以及根据所有的类对象把包含@Bean注解的类的对象创建出来
/**
 * @author 甘赵辉
 * @date 2023/2/28
 * @Purpose(目的)  工具类( 通过包名得到包下所有的对象字节数据 + @Bean注解的扫描并得到 Object数组)
 */
public class ClassUtils {


    /**
     *
     * @param classList 类对象数组
     * @return 包含@Bean注解的对象数组
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static Object[] scanClassHasBean(Class[] classList) throws InstantiationException, IllegalAccessException {

        //  创建超类数组
        Object[] objectArr = { };

        // 遍历类对象
        for (Class c: classList){
            //通过类对象拿到注解对象
            Bean annotation =   (Bean)c.getAnnotation(Bean.class);
             if(annotation==null){
                continue;
             }
             //拿到注解@Bean中的value的值
            System.out.println("ClassUtils.scanClassHasBean: "+annotation.value());
             //如果注解对象不是空
              if (annotation != null){
                  int len = objectArr.length;//原数组长度

                  //数组扩容, +1
                  objectArr= Arrays.copyOf(objectArr, len + 1);

                  Object o = c.newInstance();//throws异常
                  //打印数组长度
//                  System.out.println(objectArr.length);
                  objectArr[len] = o;
              }

        }

        return objectArr;
      }

    /**
     *  通过包名, 得到包下所有的类的全限定名数组
     * @param packageName  包名 字符串
     * @return 包下所有 类全限定名 组成的数组
     */
    public static Class[] getClassByPackage(String packageName) {
        try {
            Enumeration<URL> resources =
                    //类名.class.getClassLoader() 得到类加载器
                    //.getResources(路径)  查找具有给定名称的所有资源
                    ClassUtils.class.getClassLoader().getResources(
                            //把.替换成 /
                            packageName.replaceAll("\\.", "/")
                    );
            //resources.hasMoreElements() 测试此枚举是否包含更多元素。
            while (resources.hasMoreElements()) {
                //resources.nextElement()   如果此枚举对象至少有一个要提供的元素，则返回此枚举的下一个元素。
                URL url = resources.nextElement();
                //url.getFile() 获取此URL的文件名
                //File的list()  返回一个字符串数组， 表示的目录中的文件和目录,此处拿的是.class文件
                String[] file = new File(url.getFile()).list();

                //创建长度和file数组一样的 Class数组
                Class[] classList = new Class[file.length];
                for (int i = 0; i < file.length; i++) {
                    //file[i].replaceAll("\\.class","") 字节文件名变成 类名,即掉了.class
                    //packageName + "." + file[i].replaceAll("\\.class", "")  包名.类名拼接起来
                    classList[i] = Class.forName(packageName + "." + file[i].replaceAll("\\.class", ""));
                    //查看所有的calss对象
                    //System.out.println(classList[i]);
                }
                return classList;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
